﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Web.Caching;
using System.ComponentModel;
using NewsMine.Utilities;
using System.Collections.Concurrent;
using System.Threading;

namespace WebApp1.Controllers
{

    public class HomeController : BaseController
    {

        static ConcurrentQueue<string> UrlsToRefresh = new ConcurrentQueue<string>();
        //public static Queue<string> UrlsToRefresh = new Queue<string>();

        public static bool IsUrlRefreshJobInProgress = false;

        public void CatchAll(string id)
        {
            AddTaskTrigger();

            //string[] PassedValue = this.Request.Url.AbsolutePath.Split('/');
            //return "You are Passing Values:" + String.Join(",", PassedValue);

            bool? checkUrl = Convert.ToBoolean(this.Request.QueryString.Get("checkurl"));



            string remoteServerHost = NewsMine.Configuration.ConfigurationManager.Get("remoteServer");

            string localSubdir = NewsMine.Configuration.ConfigurationManager.Get("localSubdir");
            string targetUrl = null;

            string currentUrl = this.Request.Url.ToString();

            //if (currentUrl.EndsWith("favicon.ico"))
            //{
            //    Response.StatusCode = 404;
            //    return;
            //}

            if (currentUrl.Contains(this.Request.Url.Host + "/" + localSubdir))
            {

                targetUrl = currentUrl.Replace(this.Request.Url.Host + "/" + localSubdir, remoteServerHost);
            }
            else
            {
                targetUrl = currentUrl.Replace(this.Request.Url.Host, remoteServerHost);
            }

            #region is just testing purpose

            if (checkUrl.HasValue && checkUrl.Value == true)
            {
                Response.Write(targetUrl);
                return;
            }
            #endregion
            string html = string.Empty;

            if (targetUrl.ToLower().Contains("/search?") || targetUrl.ToLower().Contains("/search/") || targetUrl.ToLower().Contains("/go?"))
            {
                html = GetContentFromMainWebsite(targetUrl); 

                //this.Response.Expires = 2;

                this.Response.Write(html);

                return;
            }

            try
            {

                html = GetHtmlContent(targetUrl); // HttpContext.Cache.Get(targetUrl);
            }
            catch (Exception ex)
            {
                TempLogger.Log("Error while loading html from main server", ex);
            }
            this.Response.Expires = 2;

            this.Response.Write(html);
        }



        public string GetHtmlContent(string keyUrl)
        {
            object htmlContentObject = CacheAgainstUrlHelper.Get(keyUrl);

            if (htmlContentObject != null && htmlContentObject is CachedHtmlContent)
            {
                CachedHtmlContent cachedHtmlContent = (CachedHtmlContent)htmlContentObject;

                if (!HomeController.UrlsToRefresh.Contains(keyUrl) && cachedHtmlContent.CreatedTime.AddMinutes(10) < DateTime.Now)
                {
                    HomeController.UrlsToRefresh.Enqueue(keyUrl);
                    AddTaskTrigger();
                }
                return cachedHtmlContent.Html;
            }
            else
            {
                if (HomeController.UrlsToRefresh.Contains(keyUrl) == false)
                {
                    HomeController.UrlsToRefresh.Enqueue(keyUrl);
                    AddTaskTrigger();
                }
            }

            //this is excepttional
            string html = GetContentFromMainWebsite(keyUrl);

            HttpContext.Cache.Insert(keyUrl.ToLower(), html, null, DateTime.Now.AddSeconds(60 * 2), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
            return html;
        }

        public static string GetContentFromMainWebsite(string targetUrl)
        {
            string html = NewsMine.Utilities.WebHelper.DownLoadHttpTextByCompressionEnabled(targetUrl);
            return html;
        }

        #region windows service kind of stuff.

        private static CacheItemRemovedCallback OnCacheRemove = null;

        //AddTask("DoStuff", 60);
        private void AddTaskTrigger()
        {
            if (HttpContext.Cache.Get("DoStuff") == null)
                AddTask("DoStuff", 30);
        }

        DateTime lastTimeTaskAdded = DateTime.MinValue;

        private void AddTask(string name, int seconds)
        {
            if (lastTimeTaskAdded.AddSeconds(20) > DateTime.UtcNow)
                return;

            lastTimeTaskAdded = DateTime.UtcNow;

            OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
            HttpRuntime.Cache.Insert(name, seconds, null,
                DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration,
                CacheItemPriority.NotRemovable, OnCacheRemove);
        }

        public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
        {
            // do stuff here if it matches our taskname, like WebRequest
            string cacheBreakingUrl = string.Empty;
            string url = string.Empty;

            string html = string.Empty;

            DateTime startTime = DateTime.MinValue;
            DateTime endTime = DateTime.MinValue;

            while (HomeController.UrlsToRefresh.Count > 0)
            {
                try
                {

                    if (UrlsToRefresh.Count == 0)
                    {
                        Thread.Sleep(500);
                        continue;
                    }
                    url = string.Empty;
                    UrlsToRefresh.TryDequeue(out url);

                    if (string.IsNullOrEmpty(url))
                    {
                        Thread.Sleep(100);
                        continue;
                    }

                    cacheBreakingUrl = string.Empty;

                    if (url.Contains("?"))
                    {
                        cacheBreakingUrl = url + "&refreshbot=true";
                    }
                    else
                        cacheBreakingUrl = url + "?refreshbot=true";

                    html = string.Empty;

                    startTime = DateTime.UtcNow;

                    try
                    {

                        html = NewsMine.Utilities.WebHelper.DownloadHtmlFromUrl(cacheBreakingUrl);
                    }
                    catch (WebException we)
                    {
                        UrlsToRefresh.Enqueue(url);
                        TempLogger.Log("Exception while refreshing content from main server..." + we.Message, we);
                        break;
                    }
                    endTime = DateTime.UtcNow;

                    try
                    {
                        System.IO.File.AppendAllText("C:\\refreshUrls.txt", Environment.NewLine + DateTime.Now.ToString() + " - Time " + (endTime - startTime).TotalMilliseconds.ToString() + " ms." + " - " + url);
                    }
                    catch { }

                    CacheAgainstUrlHelper.Replace(url.ToLower(), new CachedHtmlContent { Html = html, CreatedTime = DateTime.UtcNow });

                    if (HttpContext.Cache.Get(url.ToLower()) != null)
                        HttpContext.Cache.Remove(url.ToLower());

                    HttpContext.Cache.Insert(url.ToLower(), html, null, DateTime.Now.AddSeconds(60 * 2), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
                }
                catch (Exception ex)
                {
                    TempLogger.Log("Error while refreshing html content for caching in the CacheItemRemoved method.", ex);
                }
            }

            // re-add our task so it recurs
            AddTask(k, Convert.ToInt32(v));
        }


        #endregion
    }
}




